# -*- coding: utf-8 -*-
import os
from loguru import logger
import stat
import xml.etree.ElementTree as ET
import math


def find_nearest_junction(net_file, target_x, target_y, tolerance=10.0):
    """
    根据给定的坐标，查找 SUMO 路网文件中最近的 junction ID。
    Args:
        net_file (str): SUMO 路网文件路径（.net.xml）。
        target_x (float): 目标 x 坐标。
        target_y (float): 目标 y 坐标。
        tolerance (float): 允许的最大距离误差，默认值为 10.0。
    Returns:
        str: 最近的 junction ID。
    """
    try:
        # 解析 XML 文件
        tree = ET.parse(net_file)
        root = tree.getroot()
    except FileNotFoundError:
        raise FileNotFoundError(f"文件 {net_file} 不存在，请检查路径。")
    except ET.ParseError:
        raise ValueError(f"无法解析 XML 文件 {net_file}，请检查文件格式。")

    nearest_junction_id = None
    min_distance = float('inf')  # 初始化最小距离为无穷大

    # 遍历所有 junction 节点
    for junction in root.findall("junction"):
        x = float(junction.get("x"))
        y = float(junction.get("y"))
        junction_id = junction.get("id")

        # 计算目标坐标与 junction 坐标的欧几里得距离
        distance = math.sqrt((x - target_x) ** 2 + (y - target_y) ** 2)

        # 如果距离小于当前最小距离，则更新最近 junction
        if distance < min_distance and distance <= tolerance:
            min_distance = distance
            nearest_junction_id = junction_id

    if nearest_junction_id is None:
        raise ValueError(f"未找到距离 ({target_x}, {target_y}) 在 {tolerance} 范围内的 junction。")

    return nearest_junction_id


def jun_E1(new_from, new_x, new_junction_id):
    """根据新的节点坐标生成新的 junction 节点字符串，并更新 shape 坐标。

    Args:
        new_x (float): 新的横坐标。
        new_junction_id (str): 新的 junction ID。

    Returns:
        str: 新的 junction 节点字符串。
    """
    # 原始的 junction 坐标
    original_x = 85.00
    original_y = 691.00
    new_id_number = new_junction_id.split('-')[-1]  # 提取编号部分，右
    new_id_number2 = new_from.split('-')[-1]  # 提取编号部分 左

    # 原始 shape 坐标
    original_shape = [
        (78.60, 701.40), (91.40, 701.40), (91.40, 680.60), (78.60, 680.60),
        (78.16, 682.82), (77.60, 683.60), (76.82, 684.16), (75.82, 684.49),
        (74.60, 684.60), (74.60, 697.40), (76.82, 697.84), (77.60, 698.40),
        (78.16, 699.18), (78.49, 700.18)
    ]
    # 计算坐标偏移量
    x_offset = new_x - original_x
    y_offset = 691.00 - original_y  # 假设新的 y 坐标不变，仍然为691.00

    # 生成新的 shape 坐标
    new_shape = [(x + x_offset, y + y_offset) for x, y in original_shape]

    # 格式化新的 shape 字符串
    shape_str = " ".join(f"{x:.2f},{y:.2f}" for x, y in new_shape)

    # 生成新的 junction 节点字符串
    junction_template = f"""
<junction id="{new_junction_id}" type="priority" x="{new_x:.2f}" y="691.00" 
    incLanes="-s1-{new_id_number}Ts2-{new_id_number}_0 -s1-{new_id_number}Ts2-{new_id_number}_1 r1-{new_id_number}Ts1-{new_id_number}_0 r1-{new_id_number}Ts1-{new_id_number}_1 {new_from}T{new_junction_id}_0 {new_from}T{new_junction_id}_1 {new_from}T{new_junction_id}_2 {new_from}T{new_junction_id}_3"
    intLanes=":s1-{new_id_number}_0_0 :s1-{new_id_number}_0_1 :s1-{new_id_number}_2_0 :s1-{new_id_number}_2_1 :s1-{new_id_number}_4_0 :s1-{new_id_number}_4_1 :s1-{new_id_number}_6_0 :s1-{new_id_number}_6_1"
    shape="{shape_str}">
    <request index="0" response="11110000" foes="11110000" cont="0"/>
    <request index="1" response="11110000" foes="11110000" cont="0"/>
    <request index="2" response="11000000" foes="11000000" cont="0"/>
    <request index="3" response="11000000" foes="11000000" cont="0"/>
    <request index="4" response="00000000" foes="00000011" cont="0"/>
    <request index="5" response="00000000" foes="00000011" cont="0"/>
    <request index="6" response="00000000" foes="00001111" cont="0"/>
    <request index="7" response="00000000" foes="00001111" cont="0"/>
</junction>
"""
    return junction_template.strip()


def s_m_n2_junction(new_from, new_x, new_junction_id, new_from_s1_1, new_to_s1_2):
    """
    根据新的x坐标和新的junction id生成junction元素及其shape，动态更新inclanes和intlanes的编号.
    Args:
        new_x (float): 新的x坐标.
        new_junction_id (str): 新的junction id（如"s2-342"）.
    Returns:
        str: 包含更新后junction和shape的XML字符串.
    """
    # 固定y坐标
    original_y = 706.00
    # 从新节点名称中提取编号
    new_id_number = new_junction_id.split('-')[-1]  # 提取编号部分 右
    new_id_number2 = new_from.split('-')[-1]  # 提取编号部分 左
    # 替换incLanes和intLanes中的编号
    inc_lanes = f"s1-{new_id_number}Ts2-{new_id_number}_0 s1-{new_id_number}Ts2-{new_id_number}_1 {new_from}T{new_junction_id}_0 {new_from}T{new_junction_id}_1 {new_from}T{new_junction_id}_2 {new_from}T{new_junction_id}_3"
    int_lanes = f":s2-{new_id_number}_0_0 :s2-{new_id_number}_0_1"
    # 偏移量
    offsets = [
        (6.4, -10.4), (-6.4, -10.4), (-6.84, -8.18), (-7.4, -7.4),
        (-8.18, -6.84), (-9.18, -6.51), (-10.4, -6.4), (-10.4, 6.4),
        (-5.27, 5.93), (-1.07, 4.53), (2.2, 2.2), (4.53, -1.07),
        (5.93, -5.27)
    ]
    # 根据偏移生成shape点
    shape_points = [
        f"{new_x + dx:.2f},{original_y + dy:.2f}" for dx, dy in offsets
    ]
    shape_str = " ".join(shape_points)

    # 生成junction元素
    junction_element = f"""
    <junction id="{new_junction_id}" type="priority" x="{new_x:.2f}" y="{original_y:.2f}"
              incLanes="{inc_lanes}" intLanes="{int_lanes}" shape="{shape_str}">
        <request index="0" response="00" foes="00" cont="0"/>
        <request index="1" response="00" foes="00" cont="0"/>
</junction>
<connection from="{new_from}T{new_junction_id}" to="-s1-{new_id_number}Ts2-{new_id_number}" fromLane="1" toLane="0" via=":s2-{new_id_number}_0_0" dir="r" state="M" />
<connection from="{new_from}T{new_junction_id}" to="-s1-{new_id_number}Ts2-{new_id_number}" fromLane="2" toLane="1" via=":s2-{new_id_number}_0_3" dir="r" state="M" />
<connection from="{new_from_s1_1}T{new_to_s1_2}" to="-r1-{new_id_number}Ts1-{new_id_number}" fromLane="1" toLane="0" via=":s1-{new_id_number}_4_0" dir="r" state="M"/>
<connection from="{new_from_s1_1}T{new_to_s1_2}" to="-r1-{new_id_number}Ts1-{new_id_number}" fromLane="2" toLane="1" via=":s1-{new_id_number}_4_3" dir="r" state="M"/>

    """
    return junction_element.strip()


def inner_E1(new_from, new_to, from_x, to_x, base_y=691.00):
    """
    根据新的起点、终点节点名称和横坐标生成edge和lane信息.
    Args:
        new_from (str): 新的起点节点名称.
        new_to (str): 新的终点节点名称.
        from_x (float): 起点的横坐标.
        to_x (float): 终点的横坐标.
        base_y (float): 基础纵坐标，默认为 691.00.
    Returns:
        str: 包含更新后 edge XML 结构的字符串.
    """
    # 定义Y坐标增量和对应的速度
    lane_data = [
        {"offset": -4.80, "speed": 8},
        {"offset": -1.60, "speed": 8},
        {"offset": 1.60, "speed": 8},
        {"offset": 4.80, "speed": 8},
    ]
    # 获取左侧端点编号部分
    new_id_number1 = new_from.split('-')[-1]  # 提取编号部分，如"342"
    new_id_number2 = new_to.split('-')[-1]  # 提取编号部分，如"342"

    # 计算长度（根据新的规则减去固定值 20.8）
    length = abs(to_x - from_x) - 20.8

    # 起点和终点的横坐标分别偏移 10.4
    shape_start_x = from_x + 10.4
    shape_end_x = to_x - 10.4

    # 生成 lanes 的 shape 和 edge 元素
    lanes = []
    for index, data in enumerate(lane_data):
        offset = data["offset"]
        speed = data["speed"]
        shape = f"{shape_start_x:.2f},{base_y + offset:.2f} {shape_end_x:.2f},{base_y + offset:.2f}"
        lanes.append(
            f'    <lane id="{new_from}T{new_to}_{index}" index="{index}" speed="{speed:.2f}" length="{length:.2f}" shape="{shape}"/>\n'
        )

    edge_xml = f"""
<edge id="{new_from}T{new_to}" from="{new_from}" to="{new_to}" priority="-1" spreadType="center">
{''.join(lanes)}</edge>
"""
    return edge_xml.strip()


def s_m_n1_connections(new_junction_id, new_to, new_from_s1_1, new_to_s1_2):
    """
    根据新的junction id更新多个connection元素的节点名称.
    Args:
        new_junction_id (str): 新的junction id（如"s2-341"）.
    Returns:
        str: 更新后的connection XML字符串.
    """
    # 提取新的节点编号
    new_id_number = new_junction_id.split('-')[-1]  # 提取编号部分  左
    new_id_number2 = new_to.split('-')[-1]  # 提取编号部分   右

    # 更新后的connection模板
    connections = f"""
    <connection from="s1-{new_id_number}Ts2-{new_id_number}" to="{new_junction_id}T{new_to}" fromLane="0" toLane="1" via=":s2-{new_id_number}_0_0" dir="r" state="M" />
    <connection from="s1-{new_id_number}Ts2-{new_id_number}" to="{new_junction_id}T{new_to}" fromLane="0" toLane="2" via=":s2-{new_id_number}_0_1" dir="r" state="M" />
    <connection from="s1-{new_id_number}Ts2-{new_id_number}" to="{new_junction_id}T{new_to}" fromLane="1" toLane="1" via=":s2-{new_id_number}_0_2" dir="r" state="M" />
    <connection from="s1-{new_id_number}Ts2-{new_id_number}" to="{new_junction_id}T{new_to}" fromLane="1" toLane="2" via=":s2-{new_id_number}_0_3" dir="r" state="M" />


    <connection from="r1-{new_id_number}Ts1-{new_id_number}" to="{new_from_s1_1}T{new_to_s1_2}" fromLane="0" toLane="1" via=":s1-{new_id_number}_4_0" dir="r" state="M"/>
    <connection from="r1-{new_id_number}Ts1-{new_id_number}" to="{new_from_s1_1}T{new_to_s1_2}" fromLane="0" toLane="2" via=":s1-{new_id_number}_4_1" dir="r" state="M"/>
    <connection from="r1-{new_id_number}Ts1-{new_id_number}" to="{new_from_s1_1}T{new_to_s1_2}" fromLane="1" toLane="1" via=":s1-{new_id_number}_4_2" dir="r" state="M"/>
    <connection from="r1-{new_id_number}Ts1-{new_id_number}" to="{new_from_s1_1}T{new_to_s1_2}" fromLane="1" toLane="2" via=":s1-{new_id_number}_4_3" dir="r" state="M"/>

    <connection from=":s1-{new_id_number}_2" to="{new_from_s1_1}T{new_to_s1_2}" fromLane="0" toLane="2" via=":s1-{new_id_number}_9_0" dir="l" state="m"/>
    <connection from=":s1-{new_id_number}_2" to="{new_from_s1_1}T{new_to_s1_2}" fromLane="1" toLane="3" via=":s1-{new_id_number}_10_0" dir="l" state="m"/>

    """
    return connections.strip()


def inner_E0(new_from, new_to, s2_121_x, s2_122_x):
    """
    根据提供的新节点名称和坐标生成 <edge> 节点，并计算车道形状和长度。
    Args:
        new_from (str): 新的起点节点名称。
        new_to (str): 新的终点节点名称。
        s2_121_x (float): s2-121 的横坐标。
        s2_122_x (float): s2-122 的横坐标。

    Returns:
        str: 生成的 <edge> 元素字符串。
    """
    # 固定参数
    y_start = 701.20  # 起点 Y 坐标
    y_increment = 3.20  # 每条车道的 Y 间距
    lane_count = 4  # 车道数量
    offset = 10.4  # 偏移量
    speed = [8, 8, 8, 8]  # 每条车道的速度

    # 获取左侧端点编号部分
    new_id_number1 = new_from.split('-')[-1]  # 提取编号部分，如"342"
    new_id_number2 = new_to.split('-')[-1]  # 提取编号部分，如"342"

    # 计算起点和终点的 X 坐标
    start_x = s2_121_x + offset
    end_x = s2_122_x - offset
    length = abs(s2_122_x - s2_121_x) - 20.8

    # 构建 <edge> 节点
    edge_id = f"E{s2_121_x:.0f}_{s2_122_x:.0f}"
    edge_priority = "-1"
    edge_spread_type = "center"

    edge_element = f'  <edge id="{new_from}T{new_to}" from="{new_from}" to="{new_to}" priority="{edge_priority}" spreadType="{edge_spread_type}">\n'

    # 构建 <lane> 节点
    for lane_index in range(lane_count):
        lane_id = f"{new_from}T{new_to}_{lane_index}"
        start_y = y_start + lane_index * y_increment
        end_y = start_y
        lane_shape = f"{start_x:.2f},{start_y:.2f} {end_x:.2f},{end_y:.2f}"
        lane_speed = speed[lane_index]
        lane_element = (
            f'    <lane id="{lane_id}" index="{lane_index}" speed="{lane_speed:.2f}" '
            f'length="{length:.2f}" shape="{lane_shape}" />\n'
        )
        edge_element += lane_element

    edge_element += "  </edge>\n"
    return edge_element


def find_nearest_2junctions(input_file, vessel_id, st_x, ed_x, ADDED_JUNCTIONS, ADDED_RANGES):
    """
    根据给定的 st_x 和 ed_x，找到 XML 文件中指定 y 值的最接近的点，并返回更新后的坐标和节点名称。
    Args:
        input_file (str): 输入的 XML 文件路径。
        st_x (float): 起点的 x 坐标。
        ed_x (float): 终点的 x 坐标。
        ADDED_JUNCTIONS (set): 已有路网的断头路节点集合。
        ADDED_RANGES (dict): 全局变量，记录每个船舶对应的路网端点坐标。
    Returns:
        dict: 返回包含 4 个参数的字典：
            new_from_s1_1 (str): y=691 起点节点名称
            new_to_s1_2 (str): y=691 终点节点名称
            s2_1_x (float): y=691 更新后的 st_x
            s2_2_x (float): y=691 更新后的 ed_x
    """
    tolerance = 10  # y 坐标的误差容忍范围
    adjacent_junction_tolerance = 30  #相邻节点的误差容忍范围

    try:
        # 解析 XML 文件
        tree = ET.parse(input_file)
        root = tree.getroot()
    except FileNotFoundError:
        raise FileNotFoundError(f"文件 {input_file} 不存在，请检查路径。")
    except ET.ParseError:
        raise ValueError(f"无法解析 XML 文件 {input_file}，请检查文件格式。")

    # 存储用于映射的变量
    new_from_s1_1, new_to_s1_2 = None, None
    s1_1_x, s1_2_x = None, None

    # 目标 y 坐标
    y_target = 691

    if st_x <-14:
        st_x = -14
        st_name = "s1-1"
        st_x_nearest = -14
    if ed_x <-14:
        ed_x = -14
        ed_name = "s1-1"
        ed_x_nearest = -14

    if st_x > 2570:
        ed_x = 2570
        ed_name = "s1-2"
        ed_x_nearest = 2570
    if ed_x > 2570:
        ed_x = 2570
        ed_name = "s1-2"
        ed_x_nearest = 2570

    # 存储符合条件的点 (x, y, id)
    points = [
        (float(junction.get("x")), float(junction.get("y")), junction.get("id"))
        for junction in root.findall("junction")
        if junction.get("x") and junction.get("y")
        and math.isclose(float(junction.get("y")), float(y_target), abs_tol=tolerance)
    ]

    if not points:
        raise ValueError(f"未找到 y={y_target} 的点，请检查输入文件。")

    # 提取 x 坐标列表及其对应的节点名称
    x_coords_with_ids = sorted((p[0], p[2]) for p in points)  # point (x, y, id)

    # 根据 ed_x 和 st_x 的相对位置进行选择
    if ed_x < st_x:
        # ed_x 找左侧横坐标最大的点，st_x 找右侧横坐标最小的点
        ed_x_nearest, ed_name = max(
            ((x, name) for x, name in x_coords_with_ids if x <= ed_x),
            default=(ed_x, "未知节点"),
        )
        st_x_nearest, st_name = min(
            ((x, name) for x, name in x_coords_with_ids if x >= st_x),
            default=(st_x, "未知节点"),
        )
    else:
        # ed_x 找右边最近的点，st_x 找左边最近的点
        ed_x_nearest, ed_name = min(
            ((x, name) for x, name in x_coords_with_ids if x >= ed_x),
            default=(ed_x, "未知节点"),
        )
        st_x_nearest, st_name = max(
            ((x, name) for x, name in x_coords_with_ids if x <= st_x),
            default=(st_x, "未知节点"),
        )

    # 检查新路网的起始点是否落入已有路网之间
    for vessel_id, (existing_st_x, existing_ed_x) in ADDED_RANGES.items():
        # 获取已有路网的范围
        existing_min = min(existing_st_x, existing_ed_x)
        existing_max = max(existing_st_x, existing_ed_x)

        # 检查新路网的起始点是否落入已有路网之间
        if st_x_nearest < ed_x_nearest:
            if existing_min <= st_x_nearest <= existing_max:  # 如果新路网在旧路网右侧，则新路网的最左侧端点自动取旧路网最右侧的端点
                st_x_nearest = existing_max
                # 找到existing_max 对应的name
                st_name = find_nearest_junction(input_file, st_x_nearest, y_target, tolerance=10.0)
                # st_name = next((name for x, name in x_coords_with_ids if x == st_x_nearest), st_name)

            elif existing_min <= ed_x_nearest <= existing_max:   # 如果新路网在旧路网左侧侧，则新路网的最右侧端点自动取旧路网最左侧的端点
                ed_x_nearest = existing_min
                st_name = find_nearest_junction(input_file, st_x_nearest, y_target, tolerance=10.0)

        elif st_x_nearest > ed_x_nearest:
            if existing_min <= ed_x_nearest <= existing_max:
                ed_x_nearest = existing_max
                st_name = find_nearest_junction(input_file, st_x_nearest, y_target, tolerance=10.0)

            elif existing_min <= st_x_nearest <= existing_max:  # 如果新路网在旧路网左侧侧，则新路网的最右侧端点自动取旧路网最左侧的端点
                st_x_nearest = existing_min
                st_name = find_nearest_junction(input_file, st_x_nearest, y_target, tolerance=10.0)
                # 如果新路网在旧路网右侧，则新路网的最左侧端点自动取旧路网最右侧的端点

    # 将节点信息存储到字典中
    junctions_ht_dict = {
        "vessel_id":vessel_id,
        "start_x": st_x_nearest,
        "new_from_s1_1": st_name,
        "new_to_s1_2": ed_name,
        "s2_1_x": st_x_nearest,
        "s2_2_x": ed_x_nearest
    }
    return junctions_ht_dict


def add_netxml(filename_before, vessel_id, st_x, ed_x, ADDED_JUNCTIONS, ADDED_RANGES, VESSEL2LANE):
    """
    批量处理船舶结果并生成新的 XML 文件，包含船舶相关数据。

    Args:
        filename_before (str): 原始 XML 文件路径。
        vessel_id (str): 当前船舶 ID。
        st_x (int): 起始点横坐标。
        ed_x (int): 结束点横坐标。
        ADDED_JUNCTIONS (set): 已有路网的断头路节点集合。
        ADDED_RANGES (dict): 全局变量，记录每个船舶对应的路网范围。

    Returns:
        str: 生成的新路网文件路径。
    """
    # 使用 find_nearest_2junctions 处理船舶停靠区投影交汇点
    junctions_ht_dict = find_nearest_2junctions(filename_before, vessel_id, st_x, ed_x, ADDED_JUNCTIONS, ADDED_RANGES)
    start_x = junctions_ht_dict["start_x"]
    new_from_s1_1 = junctions_ht_dict["new_from_s1_1"]
    new_to_s1_2 = junctions_ht_dict["new_to_s1_2"]
    new_from_s2_1 = new_from_s1_1.replace("s1", "s2")
    new_to_s2_2 = new_to_s1_2.replace("s1", "s2")

    s1_edge = new_from_s1_1 + 'T' + new_to_s1_2
    s2_edge = new_from_s2_1 + 'T' + new_to_s2_2

    if st_x < ed_x:  # 船头向右
        VESSEL2LANE[vessel_id] = {
            "vessel_id": vessel_id,
            "direction": "right",
            "start_x": start_x,
            "s1_1Ts1_2": {'edge_id': s1_edge,
                          'lanes': [s1_edge + '_0', s1_edge + '_1', s1_edge + '_2', s1_edge + '_3']},
            "s2_1Ts2_2": {'edge_id': s2_edge,
                          'lanes': [s2_edge + '_0', s2_edge + '_1', s2_edge + '_2', s2_edge + '_3']},
            "dtlane2sumolane": {0: s2_edge + '_3', 1: s2_edge + '_2', 2: s2_edge + '_1', 3: s2_edge + '_0',
                                4: s1_edge + '_3', 5: s1_edge + '_2', 6: s1_edge + '_1', 7: s1_edge + '_0'}
        }
    elif st_x > ed_x:  # 船头向左
        VESSEL2LANE[vessel_id] = {
            "vessel_id": vessel_id,
            "direction": "left",
            "start_x": start_x,
            "s1_1Ts1_2": {'edge_id': s1_edge,
                          'lanes': [s1_edge + '_0', s1_edge + '_1', s1_edge + '_2', s1_edge + '_3']},
            "s2_1Ts2_2": {'edge_id': s2_edge,
                          'lanes': [s2_edge + '_0', s2_edge + '_1', s2_edge + '_2', s2_edge + '_3']},
            "dtlane2sumolane": {0: s2_edge + '_0', 1: s2_edge + '_1', 2: s2_edge + '_2', 3: s2_edge + '_3',
                                4: s1_edge + '_0', 5: s1_edge + '_1', 6: s1_edge + '_2', 7: s1_edge + '_3'}
        }

    filename_before_base = os.path.basename(filename_before)
    initial_temp = filename_before_base.split('.')[0]
    output_dir = os.path.dirname(filename_before)
    if len(initial_temp) == 8:
        filename_after = initial_temp + '_' + vessel_id + '.net.xml'
    else:
        filename_after = initial_temp + '-' + vessel_id + '.net.xml'

    filename_after = os.path.join(output_dir, filename_after)

    # 复制原始文件到新的文件
    try:
        if os.path.exists(filename_after):
            os.remove(filename_after)
    except PermissionError as e:
        logger.error(f"权限错误: {e}")
        return

    s2_1_x = junctions_ht_dict["s2_1_x"]
    s2_2_x = junctions_ht_dict["s2_2_x"]

    # 生成 edge 和 junction 的内容
    edge_E0 = inner_E0(new_from_s2_1, new_to_s2_2, s2_1_x, s2_2_x)
    edge_E1 = inner_E1(new_from_s1_1, new_to_s1_2, s2_1_x, s2_2_x)
    junction_E1 = jun_E1(new_from_s1_1, s2_2_x, new_to_s1_2)
    junction_E0 = s_m_n2_junction(new_from_s2_1, s2_2_x, new_to_s2_2, new_from_s1_1, new_to_s1_2)
    connection = s_m_n1_connections(new_from_s2_1, new_to_s2_2, new_from_s1_1, new_to_s1_2)

    append_edge_to_xml2(filename_before, filename_after, edge_E0, edge_E1, junction_E1, junction_E0, connection,
                        vessel_id)
    ADDED_JUNCTIONS.update([new_from_s1_1, new_to_s1_2])  # 更新 added_junctions 集合
    ADDED_RANGES[vessel_id] = (s2_1_x, s2_2_x)  # 更新 ADDED_RANGES
    return filename_after


def add_netxml_vessel_data_change(filename_before, vessel_id, st_x, ed_x, ADDED_JUNCTIONS, ADDED_RANGES, VESSEL2LANE):
    """
    批量处理船舶结果并生成新的 XML 文件，包含船舶相关数据。

    Args:
        filename_before (str): 原始 XML 文件路径。
        vessel_id (str): 当前船舶 ID。
        st_x (int): 起始点横坐标。
        ed_x (int): 结束点横坐标。
        ADDED_JUNCTIONS (set): 已有路网的断头路节点集合。
        ADDED_RANGES (dict): 全局变量，记录每个船舶对应的路网范围。

    Returns:
        str: 生成的新路网文件路径。
    """
    # 使用 find_nearest_2junctions 处理船舶停靠区投影交汇点
    junctions_ht_dict = find_nearest_2junctions(filename_before, vessel_id, st_x, ed_x, ADDED_JUNCTIONS, ADDED_RANGES)
    start_x = junctions_ht_dict["start_x"]
    new_from_s1_1 = junctions_ht_dict["new_from_s1_1"]
    new_to_s1_2 = junctions_ht_dict["new_to_s1_2"]
    new_from_s2_1 = new_from_s1_1.replace("s1", "s2")
    new_to_s2_2 = new_to_s1_2.replace("s1", "s2")

    s1_edge = new_from_s1_1 + 'T' + new_to_s1_2
    s2_edge = new_from_s2_1 + 'T' + new_to_s2_2

    if st_x < ed_x:  # 船头向右
        VESSEL2LANE[vessel_id] = {
            "vessel_id": vessel_id,
            "direction": "right",
            "start_x": start_x,
            "s1_1Ts1_2": {'edge_id': s1_edge,
                          'lanes': [s1_edge + '_0', s1_edge + '_1', s1_edge + '_2', s1_edge + '_3']},
            "s2_1Ts2_2": {'edge_id': s2_edge,
                          'lanes': [s2_edge + '_0', s2_edge + '_1', s2_edge + '_2', s2_edge + '_3']},
            "dtlane2sumolane": {0: s2_edge + '_3', 1: s2_edge + '_2', 2: s2_edge + '_1', 3: s2_edge + '_0',
                                4: s1_edge + '_3', 5: s1_edge + '_2', 6: s1_edge + '_1', 7: s1_edge + '_0'}
        }
    elif st_x > ed_x:  # 船头向左
        VESSEL2LANE[vessel_id] = {
            "vessel_id": vessel_id,
            "direction": "left",
            "start_x": start_x,
            "s1_1Ts1_2": {'edge_id': s1_edge,
                          'lanes': [s1_edge + '_0', s1_edge + '_1', s1_edge + '_2', s1_edge + '_3']},
            "s2_1Ts2_2": {'edge_id': s2_edge,
                          'lanes': [s2_edge + '_0', s2_edge + '_1', s2_edge + '_2', s2_edge + '_3']},
            "dtlane2sumolane": {0: s2_edge + '_0', 1: s2_edge + '_1', 2: s2_edge + '_2', 3: s2_edge + '_3',
                                4: s1_edge + '_0', 5: s1_edge + '_1', 6: s1_edge + '_2', 7: s1_edge + '_3'}
        }

    # 输入文件名处理，与 delete_netxml 一致
    filename_before_base = os.path.basename(filename_before)
    str1 = filename_before_base.split(".")[0]
    str1 = str1[:-3] if str1.endswith('_id') else str1  # 去掉可能的 _id
    date1 = str1[0:8]  # 提取日期
    str2 = str1[9:] if len(str1) > 8 else ""  # 提取已有船舶ID部分
    vessel_id_list = str2.split("-") if str2 else []  # 分割已有船舶ID

    # 输出文件名处理：添加新 vessel_id
    remaining_vessel_ids = vessel_id_list + [vessel_id]  # 添加新船舶ID
    new_filename = os.path.join(os.path.dirname(filename_before), f"{date1}_{'-'.join(remaining_vessel_ids)}_id.net.xml")

    # 复制并更新文件内容
    try:
        if os.path.exists(new_filename):
            os.remove(new_filename)
    except PermissionError as e:
        logger.error(f"权限错误: {e}")
        return

    s2_1_x = junctions_ht_dict["s2_1_x"]
    s2_2_x = junctions_ht_dict["s2_2_x"]

    # 生成 edge 和 junction 的内容
    edge_E0 = inner_E0(new_from_s2_1, new_to_s2_2, s2_1_x, s2_2_x)
    edge_E1 = inner_E1(new_from_s1_1, new_to_s1_2, s2_1_x, s2_2_x)
    junction_E1 = jun_E1(new_from_s1_1, s2_2_x, new_to_s1_2)
    junction_E0 = s_m_n2_junction(new_from_s2_1, s2_2_x, new_to_s2_2, new_from_s1_1, new_to_s1_2)
    connection = s_m_n1_connections(new_from_s2_1, new_to_s2_2, new_from_s1_1, new_to_s1_2)

    append_edge_to_xml2(filename_before, new_filename, edge_E0, edge_E1, junction_E1, junction_E0, connection, vessel_id)
    ADDED_JUNCTIONS.update([new_from_s1_1, new_to_s1_2])  # 更新 added_junctions 集合
    ADDED_RANGES[vessel_id] = (s2_1_x, s2_2_x)  # 更新 ADDED_RANGES
    return new_filename


def delete_netxml(net_filename, delete_vessel_list, ADDED_JUNCTIONS, ADDED_RANGES, VESSEL2LANE):
    """
    根据船舶ID列表删除XML文件中对应的数据，并生成符合命名规则的输出文件名。
    Args:
        net_filename (str): 原始 XML 文件路径。
        delete_vessel_list (list): 要删除的船舶 ID 列表。
    Returns:
        str: 生成的输出文件名。
    """
    for vessel_id in delete_vessel_list:
        VESSEL2LANE.pop(vessel_id, None)

    NET_FILENAME_TEMP = os.path.basename(net_filename)
    # 动态生成输出文件名
    str1 = NET_FILENAME_TEMP.split(".")[0]
    str1 = str1[:-3]
    date1 = str1[0:8]
    str2 = str1[9:]
    vessel_id_list = str2.split("-")
    # 移除要删除的船舶ID
    remaining_vessel_ids = [vessel_id for vessel_id in vessel_id_list if vessel_id not in delete_vessel_list]
    # 添加原始路径，并在文件名中加上 _id
    new_filename = os.path.join(os.path.dirname(net_filename), f"{date1}_{'-'.join(remaining_vessel_ids)}_id.net.xml")

    with open(net_filename, 'r', encoding='utf-8') as file:
        lines = file.readlines()
    new_content = []
    inside_vessel_data = False  # 用于标记是否在要删除的船舶数据之间
    deleted_junctions = set()  # 用于记录被删除路网的断头路节点

    for line in lines:   # 检查是否是要删除的船舶ID开始标记
        if any(f"# 船舶ID: {vessel_id}" in line for vessel_id in delete_vessel_list):
            inside_vessel_data = True
            # deleted_junctions.update(parse_junctions_from_vessel_data(lines, lines.index(line)))
        # 如果在船舶数据之间，跳过这些行
        if inside_vessel_data:
            if any(f"# /船舶ID: {vessel_id}" in line for vessel_id in delete_vessel_list):
                inside_vessel_data = False  # 找到结束注释，标记结束
            continue
        # 如果不在删除的范围内，正常添加行
        new_content.append(line)

    with open(new_filename, 'w', encoding='utf-8') as file:
        file.writelines(new_content)

    # 更新 added_junctions 集合，移除被删除路网的断头路节点
    ADDED_JUNCTIONS -= deleted_junctions

    # 更新 ADDED_RANGES，移除被删除船舶的路网范围
    for vessel_id in delete_vessel_list:
        if vessel_id in ADDED_RANGES:
            del ADDED_RANGES[vessel_id]
    return new_filename


def append_edge_to_xml2(input_file_path, output_file_path, edge_E0, edge_E1, junction_E1, junction_E0, connection, vessel_id):
    """
    将生成的 <edge> 内容插入到目标 XML 文件的 </net> 标签之前，并保存到新的文件中。
    Args:
        input_file_path (str): 原始 XML 文件路径。
        output_file_path (str): 修改后保存的 XML 文件路径。
        edge_E0 (str): 生成的 edge_E0 内容。
        edge_E1 (str): 生成的 edge_E1 内容。
        junction_E1 (str): 生成的 junction_E1 内容。
        junction_E0 (str): 生成的 junction_E0 内容。
        connection (str): 生成的 connection 内容。
    Returns:
        None
    """
    # 读取文件内容
    os.chmod(input_file_path, stat.S_IWRITE | stat.S_IREAD)  # 修改文件权限
    with open(input_file_path, 'r+', encoding='utf-8') as file:
        lines = file.readlines()
    # os.chmod(input_file_path, stat.S_IWRITE | stat.S_IREAD)

    # 找到 </net> 标签，并在之前插入新内容
    new_content = []
    for line in lines:
        if line.strip() == "</net>":
            # 添加船舶 ID 标记
            new_content.append(f"# 船舶ID: {vessel_id} \n")
            # 插入各个部分
            new_content.append(edge_E0 + "\n")  # 在 </net> 前插入
            new_content.append(edge_E1 + "\n")  # 在 </net> 前插入
            new_content.append(junction_E1 + "\n")  # 在 </net> 前插入
            new_content.append(junction_E0 + "\n")  # 在 </net> 前插入
            new_content.append(connection + "\n")  # 在 </net> 前插入
            # 添加船舶 ID 结束标记
            new_content.append(f"# /船舶ID: {vessel_id} \n")
        new_content.append(line)

    # 写入新文件
    with open(output_file_path, 'w', encoding='utf-8') as file:
        file.writelines(new_content)#####写文件


if __name__ == "__main__":
    # 输入文件路径、船舶ID以及起始和结束横坐标
    filename_before = "20241220.net.xml"  # 原始 XML 文件路径
    vessel_id = "vesselID1"  # 当前船舶的 ID
    st_x = 800  # 起始横坐标
    ed_x = 200  # 结束横坐标
    add_netxml(filename_before, vessel_id, st_x, ed_x)
